<template>
  <div class="component component-interface">
    <table class="d-table d-table-striped d-table-bordered d-table-hover">
      <thead>
        <tr>
          <th v-if="isRadio">选择</th>
          <th>
            <span class="d-text-primary d-text-linker icon-switch" @click="handleChangeMode">
              <SwitchRoundIcon />
              {{ mode === 'mock' ? '字段编辑' : '模拟与验证' }}
            </span>
            <i class="d-text-danger">*</i>字段名称
          </th>
          <th v-if="mode !== 'mock'"><i class="d-text-danger">*</i>字段类型</th>
          <th v-if="mode !== 'mock'">长度</th>
          <th v-if="mode !== 'mock'">默认值</th>
          <th v-if="mode !== 'mock'">是否主键</th>
          <th v-if="mode !== 'mock'">是否必需</th>
          <th v-if="mode !== 'mock'">注释</th>
          <th v-if="mode === 'mock'">模拟类型</th>
          <th v-if="mode === 'mock'">
            模拟规则
            <a :href="getMicroPath('#/service/inter/syntax')" class="d-text-linker d-text-theme" title="数据模拟生成规则说明" target="_blank"><QuestionIcon /></a>
          </th>
          <th v-if="mode === 'mock'">模拟值</th>
          <th v-if="mode === 'mock'">是否验证</th>
          <th v-if="mode === 'mock'">验证规则</th>
          <th class="wide-sm">操作</th>
        </tr>
      </thead>
      <tbody>
        <tr
          class="param-row drag-box"
          :class="item.isSign ? 'row-sign' : ''"
          v-for="(item, i) in paramData.children" :key="item.id"
          v-show="!item.isHide"
        >
          <td class="vlign-mid" v-if="isRadio">
            <div class="form-radio wide-xxs text-center">
              <input type="radio"
                name="param_radio"
                class="d-form-radio v-top"
                :value="item"
                v-model="checked"
              />
            </div>
          </td>
          <td>
            <div class="wide-xlg">
              <div class="box-flex">
                <div class="item-gap">
                  <span :class="'gap-wide gap-wide-' + item.level"></span>
                  <span class="gap-empty" v-if="item.level && (!item.childrenLength || item.childrenLength < 1)"></span>
                  <ArrowRightIcon v-if="item.isCollapse" @click="expandNode(item)" class="gap-icon" />
                  <ArrowDownIcon v-else @click="expandNode(item)" class="gap-icon" />
                </div>
                <input
                  class="d-form-input" type="text"
                  placeholder="字母与数字组合"
                  maxlength="40"
                  v-model="item.name"
                />
              </div>
            </div>
          </td>
          <td v-if="mode !== 'mock'">
            <div class="wide-sm cell-flex">
              <select class="d-form-select" v-model="item.type" @change="handleChangeType(item)">
                <option value="string">字符串</option>
                <option value="number">数字</option>
                <option value="boolean">布尔值</option>
                <option value="object">对象</option>
                <option value="array">数组</option>
              </select>
            </div>
          </td>
          <td v-if="mode !== 'mock'">
            <div class="wide-md">
              <input
                class="d-form-input" type="text"
                :disabled="isObjectType(item) ? true : false"
                v-model="item.length"
              />
            </div>
          </td>
          <td v-if="mode !== 'mock'">
            <div class="wide-md">
              <input
                class="d-form-input" type="text"
                :disabled="isObjectType(item) ? true : false"
                v-model="item.value"
              />
            </div>
          </td>
          <td v-if="mode !== 'mock'">
            <select class="d-form-select wide-xs" v-model="item.primaryKey">
              <option v-for="item in judgeOptions" :key="item.id" :value="item.id">{{ item.text }}</option>
            </select>
          </td>
          <td v-if="mode !== 'mock'">
            <select class="d-form-select wide-xs" v-model="item.required">
              <option v-for="item in judgeOptions" :key="item.id" :value="item.id">{{ item.text }}</option>
            </select>
          </td>
          <td v-if="mode !== 'mock'">
            <input
              class="d-form-input" type="text"
              placeholder=""
              v-model="item.comment"
            />
          </td>
          <td v-if="mode === 'mock'">
            <div class="wide-sm cell-flex">
              <select class="d-form-select" v-model="item.ruleType">
                <option value="default">默认</option>
                <option value="regexp">正则</option>
                <option value="ratio">比例分配</option>
              </select>
            </div>
          </td>
          <td v-if="mode === 'mock'">
            <div class="wide-md">
              <input
                class="d-form-input" type="text"
                value=""
                placeholder=""
                :disabled="isObjectType(item, true) ? true : false"
                v-model="item.rule"
              />
            </div>
          </td>
          <td v-if="mode === 'mock'">
            <div class="wide-md">
              <input
                class="d-form-input" type="text"
                :disabled="isObjectType(item) ? true : false"
                v-model="item.ruleValue"
              />
            </div>
          </td>
          <td v-if="mode === 'mock'">
            <select class="d-form-select wide-xs" v-model="item.valid">
              <option v-for="item in judgeOptions" :key="item.id" :value="item.id">{{ item.text }}</option>
            </select>
          </td>
          <td v-if="mode === 'mock'">
            <input
              class="d-form-input" type="text"
              :disabled="isObjectType(item) ? true : false"
              v-model="item.validRule"
            />
          </td>
          <td class="d-vm d-vm-actions">
            <div class="d-bar-tools d-bar-tools-condensed d-grid-actions">
              <a v-if="!!i" @click="addParam(item)" class="d-tools-item d-text-linker" title="添加平级参数"><PlusIcon size="sm" /></a>
              <a v-if="isObjectType(item)" @click="addSubParam(item)" class="d-tools-item d-text-linker" title="添加子参数"><PlusRoundIcon size="sm" /></a>
              <a v-if="false" v-drag="handleDrag(item)" class="d-tools-item d-text-linker" title="拖拽排序"><DragIcon size="sm" /></a>
              <a v-if="isShowDel(item)" @click="delParam(item)" class="d-tools-item d-text-linker" title="删除"><DeleteIcon size="sm" /></a>
              <span class="d-dropdown d-drop-hover d-drop-right d-tools-item d-text-linker">
                  <MenuIcon title="更多" />
                  <div class="d-list-menu d-list-cascade d-list-cascade-right">
                    <ul class="d-list-menu-group">
                      <li v-if="!!i" @click="addCloneParam(item)" class="d-list-menu-item">
                        <a class="d-list-item-row">
                          <CloneIcon size="sm" /><span class="d-list-item-text">克隆</span>
                        </a>
                      </li>
                      <li v-if="isChoose" @click="showParamsTpl(item)" class="d-list-menu-item">
                        <a class="d-list-item-row">
                          <ListStyleIcon size="sm" /><span class="d-list-item-text">参数选择</span>
                        </a>
                      </li>
                      <li @click="showParamImport(item)" class="d-list-menu-item">
                        <a class="d-list-item-row">
                          <UploadIcon size="sm" /><span class="d-list-item-text">JSON导入</span>
                        </a>
                      </li>
                      <li @click="showParamBeanImport(item)" class="d-list-menu-item">
                        <a class="d-list-item-row">
                          <UploadIcon size="sm" /><span class="d-list-item-text">Bean导入</span>
                        </a>
                      </li>
                      <li @click="copyParam(item)" class="d-list-menu-item">
                        <a class="d-list-item-row">
                          <CopyIcon size="sm" /><span class="d-list-item-text">复制</span>
                        </a>
                      </li>
                      <li @click="pasteParam(item)" class="d-list-menu-item">
                        <a class="d-list-item-row">
                          <PasteIcon size="sm" /><span class="d-list-item-text">粘贴</span>
                        </a>
                      </li>
                      <li v-if="!!i" @click="sign(item)" class="d-list-menu-item">
                        <a class="d-list-item-row">
                          <SignIcon size="sm" /><span class="d-list-item-text">{{String(item.isSign) === '1' ? '取消标记' : '标记'}}</span>
                        </a>
                      </li>
                    </ul>
                  </div>
                </span>
            </div>
          </td>
        </tr>
      </tbody>
    </table>
    <Dialoger ref="diaImportParam" title="导入JSON参数" @sure="importParamsItem">
      <template v-slot:body>
        <ImportParamView ref="importParamView" />
      </template>
    </Dialoger>
    <Dialoger ref="diaImportBeanParam" width="600px" title="导入Bean参数" @sure="importBeanParamsItem">
      <template v-slot:body>
        <ImportBeanView ref="importBeanParamView" />
      </template>
    </Dialoger>
  </div>
</template>

<script>
/* 接口参数 */
import { objecter, strer } from '@daelui/dogjs/dist/components.js'
import { Dialoger, Messager } from '@daelui/vdog/dist/components.js'
import {
  MenuIcon, EditIcon, PlusIcon, PlusRoundIcon, DeleteIcon, CopyIcon, DragIcon,
  ListStyleIcon, UploadIcon, PasteIcon, SignIcon, CloneIcon, SwitchRoundIcon,
  ArrowRightIcon, ArrowDownIcon, QuestionIcon
} from '@daelui/vdog/dist/icons.js'
import ImportParamView from './import-param'
import ImportBeanView from './import-bean'
import interBis from './business/interface.js'
import { state } from '@/service/stock/index'

export default {
  components: {
    Dialoger,
    ImportParamView,
    ImportBeanView,
    MenuIcon,
    EditIcon,
    PlusIcon,
    PlusRoundIcon,
    DeleteIcon,
    CopyIcon,
    DragIcon,
    ListStyleIcon,
    UploadIcon,
    PasteIcon,
    SignIcon,
    CloneIcon,
    SwitchRoundIcon,
    ArrowRightIcon,
    ArrowDownIcon,
    QuestionIcon
  },

  props: {
    // 参数数据
    params: {
      default: {
        isCollapse: false,
        children: []
      }
    },
    // 是否允许单选
    isRadio: {
      default: false
    },
    // 是否可选择参数
    isChoose: {
      default: true
    }
  },

  data () {
    return {
      // 参数数据
      paramData: {
        isCollapse: false,
        children: []
      },
      // 选择的参数
      checked: null,
      // 显示模式
      mode: '',
      // 布尔值
      judgeOptions: state.judgeOptions
    }
  },

  methods: {
    /**
     * @function 切换字段模式
    */
    handleChangeMode () {
      this.mode = this.mode === 'mock' ? '' : 'mock'
    },

    /**
     * @function 切换字段类型,更新模拟类型
    */
    handleChangeType (item) {
      let type = item.type
      if (!type || item.ruleType) {
        return true
      }
      item.ruleType = 'default'
    },

    /**
     * @function 打开节点
     * @param {Object} node 节点对象
    */
    expandNode (node) {
      // 节点折叠取反
      this.$set(node, 'isCollapse', !node.isCollapse)
      // 获取关联节点
      let nodes = this.getRelaParams(this.paramData, node)
      nodes.slice(1).forEach(item => {
        this.$set(item, 'isHide', node.isCollapse)
        this.$set(item, 'isCollapse', false)
      })
    },
    /**
     * @function 是否是对象类型参数
     * @param {Object} item // 参数对象
     * @param {Boolean} flag // 是否是纯对象
     * @return {Boolean}
    */
    isObjectType (item, flag) {
      let types = ['object']
      if (!flag) {
        types.push('array')
      }
      let type = item.type
      return types.indexOf(type) > -1
    },

    /**
     * @function 是否是唯一的参数
     * @param {Object} item // 参数对象
     * @return {Boolean}
    */
    isShowDel (item) {
      let param = this.paramData
      // 根参数数组
      let rootArr = []
      rootArr = param.children.filter(node => {
        return node.pid === 0
      })

      return !(rootArr.length < 2 && item.pid === 0)
    },

    /**
     * @function 获取新的参数对象
     * @param {Object} item // 参数对象
     * @param {Boolean} isSub // 是否是子参数
     * @return {Object}
    */
    getNewParam (item, isSub) {
      let param = {
        id: strer.utid(12),
        name: '',
        type: 'string',
        ruleType: 'default',
        primaryKey: 0,
        required: 1,
        value: '',
        length: 20,
        rule: '1',
        ruleValue: '',
        comment: '',
        valid: 0,
        pid: isSub ? item.id : (item.pid || 0),
        isSign: 0,
        level: isSub ? item.level + 1 : item.level
      }

      return param
    },

    /**
    * @function 添加参数
    * @param {Object} item // 参数对象
    */
    addParam (item, type) {
      let param = this.paramData
      // 参数索引
      let index = param.children.indexOf(item)
      // 关联参数
      let relaParams = this.getRelaParams(param, item)
      let newItem = this.getNewParam(item)
      // 添加新的参数对象
      param.children.splice(index + relaParams.length, 0, newItem)
      // 计算节点下子节点的数目
      interBis.countChildren(param.children)

      return newItem
    },

    /**
     * @function 克隆参数
     * @param {String} type // 类型
    */
    showParamsTpl (param, type) {
      this.paraming = param
      this.paramType = type
      this.$emit('onChoose', this)
    },

    /**
    * @function 设置参数
    * @param {Object} item // 参数对象
    */
    setParam (param) {
      if (param) {
        param = objecter.clone(param, true)
        param.id = strer.utid(12)
        this.replaceParam(param, this.paraming)
      }
    },

    /**
    * @function 替换参数
    * @param {Object} item // 参数对象
    */
    replaceParam (newParam, paramItem) {
      let param = this.paramData

      // 参数索引
      let index = param.children.indexOf(paramItem)
      // 关联参数
      let relaParams = this.getRelaParams(param, paramItem)
      // 解析
      let params = interBis.unPackParams([newParam], null, paramItem.level, true)
      params[0].pid = paramItem.pid
      params[0].name = paramItem.name || params[0].name
      let args = [index, relaParams.length]
      args = args.concat(params)
      // 添加新的参数对象
      param.children.splice.apply(
        param.children, args
      )
    },

    /**
    * @function 查找关联参数
    * @param {Object} param // 参数类型对象
    * @param {Object} item // 参数对象
    * @param {Array<Object>} [params] // 参数数组
    * @return {Array<Object>}
    */
    getRelaParams (param, item, params) {
      params = Array.isArray(params) ? params : [item]
      // 遍历参数查找所有子参数
      param.children.forEach(node => {
        if (item.id === node.pid) {
          params.push(node)
          this.getRelaParams(param, node, params)
        }
      })

      return params
    },

    /**
    * @function 获取克隆参数
    * @param {Array<Object>} params // 参数数组
    * @return {Array<Object>}
    */
    getCloneParams (params) {
      params = Array.isArray(params) ? params : [params]
      let map = new Map()
      // 复制参数
      params = params.map(node => {
        let newItem = this.getNewParam(node)
        // 拷贝属性
        for (let key in newItem) {
          newItem[key] = node[key]
        }
        // 参数新id
        let newId = strer.utid(12)
        map.set(newItem.id, newId)
        newItem.id = newId
        // 有父参数id
        if (map.has(newItem.pid)) {
          newItem.pid = map.get(newItem.pid)
        }

        return newItem
      })

      return params
    },

    /**
    * @function 克隆参数
    * @param {Object} item // 参数对象
    */
    addCloneParam (item) {
      let param = this.paramData
      // 参数索引
      let index = param.children.indexOf(item)
      // 关联参数
      let relaParams = this.getRelaParams(param, item)
      // 复制
      relaParams = this.getCloneParams(relaParams)
      let args = [index + relaParams.length, 0]
      args = args.concat(relaParams)
      // 添加新的参数对象
      param.children.splice.apply(
        param.children, args
      )
      // 计算节点下子节点的数目
      interBis.countChildren(param.children)
    },

    /**
    * @function 添加请求子级参数
    * @param {Object} item // 参数对象
    */
    addSubParam (item) {
      let param = this.paramData
      // 参数索引
      let index = param.children.indexOf(item)
      // 添加新的参数对象
      param.children.splice(index + 1, 0, this.getNewParam(item, true))
      // 计算节点下子节点的数目
      interBis.countChildren(param.children)
    },

    /**
     * @function 删除请求参数
    */
    delParam (item) {
      let param = this.paramData
      // 参数索引
      let index = param.children.indexOf(item)
      let paramIds = [item.id] // 参数与子参数id集合
      let len = 1 // 删除的参数长度
      // 遍历参数查找所有子参数
      param.children.forEach(node => {
        if (paramIds.indexOf(node.pid) > -1) {
          paramIds.push(node.id)
          len += 1
        }
      })

      // 删除参数对象
      param.children.splice(index, len)
      // 计算节点下子节点的数目
      interBis.countChildren(param.children)
    },

    /**
    * @function 显示导入参数视图
    * @param {String} type // 类型
    */
    showParamImport (item, type) {
      this.paramType = type
      this.imParamItem = item
      this.$refs.importParamView.load()
      this.$refs.diaImportParam.show()
    },

    /**
    * @function 导入参数
    */
    importParamsItem () {
      let params = this.$refs.importParamView.getState()
      if (params) {
        // 解析导入的参数
        params = interBis.resolveParams(params)
        this.replaceParam(params, this.imParamItem)
        this.$refs.diaImportParam.hide()
      }
    },

    /**
    * @function 显示导入Bean参数视图
    * @param {String} type // 类型
    */
    showParamBeanImport (item, type) {
      this.paramType = type
      this.imParamItem = item
      this.$refs.importBeanParamView.load()
      this.$refs.diaImportBeanParam.show()
    },

    /**
    * @function 导入Bean参数
    */
    importBeanParamsItem () {
      let params = this.$refs.importBeanParamView.getState()
      if (params) {
        // 解析导入的参数
        params = interBis.resolveBeanParams(params)
        this.replaceParam(params, this.imParamItem)
        this.$refs.diaImportBeanParam.hide()
      }
    },

    /**
     * @function 标记参数
     * @param {Object} item // 参数配置对象
    */
    sign (item) {
      // 取反
      let isSign = String(item.isSign) === '1' ? 0 : 1
      this.$set(item, 'isSign', isSign)
    },

    /**
     * @function 拖拽处理
    * @param {Object} param // 参数对象
    */
    handleDrag (param) {
      return {
        module: param,
        bindCall: (el, value) => {
          let $el = $(el)
          let $tr = $el.closest('.drag-box')
          // 拖拽效果展示元素
          let $dragEl = $('<div class="drager-param"></div>').appendTo($tr)
          // 保存模块对象
          $dragEl.get(0).data = value
          return {
            $el: $el,
            $dragEl: $dragEl
          }
        },
        downCall (drager) {
          let $dragEl = drager.$dragEl
          let $tr = $dragEl.closest('.drag-box')
          let offset = $tr.offset()
          $dragEl.css({
            top: (offset.top - $(window).scrollTop()) + 'px',
            left: (offset.left - $(window).scrollLeft()) + 'px',
            width: $tr.width(),
            height: $tr.height()
          })
          drager.$dragEl.show()
        },
        upCall: (drager, oldStyle, oldPos, mouPos, e) => {
          // 数据模块
          let module = drager.$dragEl.get(0).data.module
          // 当前拖拽元素的坐标值
          let top = drager.$dragEl.offset().top
          drager.$dragEl.hide()
          // 计算兄弟元素坐标
          let $siblings = drager.$dragEl.closest('.drag-box').siblings()
          // 过滤非同级的元素
          $siblings = $siblings.filter(function () {
            let item = $(this).find('.drager-param').get(0)
            let itemData = item && item.data ? item.data : null
            if (itemData && itemData.module.pid === module.pid) {
              return true
            }
            return false
          })

          // 坐标记录
          let coords = []
          $siblings.each(function () {
            let $item = $(this)
            let top = $item.offset().top
            coords.push({
              top: top,
              bottom: parseFloat($item.height()) + top
            })
          })

          // 距离比较
          let min = 10000000 // 最小距离值
          let minAbs = min // 最小距离绝对值
          let data = null // 模块数据
          let dragType = 'before'
          coords.forEach((item, i) => {
            let diffTop = top - item.top
            let diffBottom = top - item.bottom
            let itemData = $siblings.eq(i).find('.drager-param').get(0).data

            // 靠近顶部
            if (Math.abs(diffTop) < minAbs) {
              min = diffTop
              minAbs = Math.abs(min)
              dragType = 'before'
              data = itemData
            }
            // 靠近底部
            if (Math.abs(diffBottom) < minAbs) {
              min = diffBottom
              minAbs = Math.abs(min)
              dragType = 'after'
              data = itemData
            }
          })

          // 样式重置
          drager.$dragEl.css({
            left: 0,
            top: 0
          })
          // 元素下方
          if (dragType === 'before' && min > 0) {
            dragType = 'after'
          }
          // 组件回调
          if (data) {
            let dragParam = this.paramData
            this.dragUpCall(
              dragParam,
              module,
              data.module,
              dragType
            )
          }
        }
      }
    },

    /**
     * @function 拖拽完成时回调
    */
    dragUpCall (dragParam, dragModule, updateModule, type) {
      let paramlList = []
      // 拖拽参数的关联参数数组
      let relaParams = this.getRelaParams(dragParam, dragModule)
      // 更新参数的关联参数长度
      let updateLen = this.getRelaParams(dragParam, updateModule).length
      // 遍历重新排序
      dragParam.children.forEach(item => {
        let hasFlag = false
        relaParams.forEach(node => {
          if (item.id === node.id) {
            hasFlag = true
          }
        })
        // 只添加不参与位置替换的元素
        if (!hasFlag) {
          paramlList.push(item)
        }
      })
      // 更新顺序
      let updateIndex = null
      paramlList.forEach((item, i) => {
        if (item.id === updateModule.id) {
          if (type === 'before') {
            updateIndex = i
          }
          else {
            updateIndex = i + updateLen
          }
        }
      })
      // 位置替换
      let args = [updateIndex, 0]
      args = args.concat(relaParams)
      paramlList.splice.apply(
        paramlList, args
      )
      // 重置模块数据
      dragParam.children = paramlList
    },

    /**
     * @function 复制参数
     * @param {Object} item 参数配置对象
    */
    copyParam (item) {
      // 包装参数
      let params = interBis.packParams(
        objecter.clone(this.paramData.children)
      )
      // 选择节点树
      let data = interBis.getMatchNode(item, params)
      // 节点存在
      if (data) {
        data = interBis.formatParams(
          data, true
        )
        localStorage.setItem('inter-param-paste', JSON.stringify(data))
        Messager.success('复制成功')
      } else {
        Messager.error('复制失败')
      }
    },

    /**
     * @function 粘贴参数
     * @param {Object} item 参数配置对象
    */
    pasteParam (item) {
      let data = localStorage.getItem('inter-param-paste')
      let param = null
      if (data && /\[|\{/.test(data)) {
        try {
          param = JSON.parse(data)
        } catch (e) {
          param = null
        }
        if (param) {
          param = objecter.clone(param, true)
          param.id = strer.utid(12)
          this.replaceParam(param, item)
        }
      }

      // 数据不存在
      if (!param) {
        Messager.error('未复制参数')
      }
    }
  },

  beforeMount () {
    this.paramData = this.params
  },

  watch: {
    params () {
      this.paramData = this.params
    }
  }
}
</script>

<style lang="less" scoped>
.component { 
  padding-bottom: 240px;
  .d-list-item-row {
    .d-list-item-text {
      padding-left: 8px;
    }
  }
}
</style>

<style lang="less">
.component-interface {
  padding-bottom:100px;
  &:after{
    content: "";
    display: block;
    clear: both;
  }
  .block{
    margin-bottom: 25px;
  }
  .form-horizontal{
    .form-group{
      margin-left:0;
      margin-right:0;
      margin-bottom:5px;
    }
  }
  .row-sign{
    &,.d-form-input,.d-form-select{
      color:#ff1f00;
    }.d-form-input,.d-form-select{
      border-color:#ff1f00;
    }
  }
  td{
    .glyphicon + .glyphicon{
      margin-left: 5px;
    }
  }
  .icon-switch{
    float: right;
    font-weight: 400;
    &:before{
      margin-right: 2px;
    }
  }
  .box-inter{
    display:flex;
    align-items: center;
  }
  .inter-gap{
    display: block;
    white-space: nowrap;
    span{
      display:inline-block;
      min-width: 10px;
    }
  }
  .box-flex{
    display:flex;
    align-items: center;
    .item-gap{
      display: block;
      padding-right: 5px;
      white-space: nowrap;
      user-select: none;
    }
    .gap-wide{
      display: inline-block;
    }
    .gap-icon{
      display: inline-block;
      width: 15px;
      cursor: pointer;
    }
    .gap-empty{
      display: inline-block;
      width: 15px;
    }
    // 遍历
    .gap-width(@n, @i: 0) when (@i =< @n) {
      .gap-wide-@{i}{
        width: 0px + @i * 25;
      }
      .gap-width(@n, (@i + 1));
    }
    .gap-width(15, 1);
  }
  .item-content{
    position: relative;
    cursor: pointer;
    &:before{
      content: "";
      position: absolute;
      left:0;
      top: 50%;
      margin-top: -10px;
      height: 20px;
      width: 2px;
      background: #1abd9e;
    }
  }
  .cell-flex{
    display: flex;
    .item-btn-type{
      width:24px;
      line-height:32px;
      text-align:center;
      &:hover{
        color:#17a78b;
      }
    }
  }
  .item-header{
    background: #fafafa;
  }
  .textarea-xl{
    min-height: 240px;
  }
}
@media (min-width: 1200px) {
  // .component-interface{
  //   .wide-xlg{
  //     min-width: 300px;
  //     width: auto;
  //   }
  // }
}
</style>
